import {
  Directive,
  Input,
  OnInit,
  OnChanges,
  Output,
  EventEmitter,
  ChangeDetectorRef,
  AfterViewInit,
  ViewContainerRef,
  ComponentFactoryResolver,
  TemplateRef,
  ViewChild,
} from '@angular/core';

import { fromEvent, Observable, interval } from 'rxjs';
import { throttle } from 'rxjs/operators';
// import { Observable } from 'rxjs';

import { NzMessageService, InputNumber, NzSpinComponent } from 'ng-zorro-antd';
import { HttpService } from 'lbf';
import { SupData } from '@core/lb/SupData';
import { ChartWrapperComponent } from '@shared/components/chart-wrapper/chart-wrapper.component';

import { LbBasicBarComponent } from '@shared/lbchart-components/lbBasicBar/lb-basic-bar.component';
import { LbGroupBarComponent } from '@shared/lbchart-components/lbGroupBar/lb-group-bar.component';
import { LbStackBarComponent } from '@shared/lbchart-components/lbStackBar/lb-stack-bar.component';
import { LbBasicLineComponent } from '@shared/lbchart-components/lbBasicLine/lb-basic-line.component';
import { LbMutipleLineComponent } from '@shared/lbchart-components/lbMutipleLine/lb-mutiple-line.component';
import { LbBasicPieComponent } from '@shared/lbchart-components/lbBasicPie/lb-basic-pie.component';
import { LbNightingalePieComponent } from '@shared/lbchart-components/lbNightingalePie/lb-nightingale-pie.component';
import { LbBasicPointComponent } from '@shared/lbchart-components/lbBasicPoint/lb-basic-point.component';
import { LbGroupPointComponent } from '@shared/lbchart-components/lbGroupPoint/lb-group-point.component';
import { LbStackLineComponent } from '@shared/lbchart-components/lbStackLine/lb-stack-line.component';
import { LbBasicHeatmapComponent } from '@shared/lbchart-components/lbBasicHeatmap/lb-basic-heatmap.component';
import { LbBasicGaugeComponent } from '@shared/lbchart-components/lbBasicGauge/lb-basic-gauge.component';
import { LbBasicFunnelComponent } from '@shared/lbchart-components/lbBasicFunnel/lb-basic-funnel.component';
import { LbBasicRadarComponent } from '@shared/lbchart-components/lbBasicRadar/lb-basic-radar.component';
import { LbStackPieComponent } from '@shared/lbchart-components/lbStackPie/lb-stack-pie.component';
import { LbBasicWordcloudComponent } from '@shared/lbchart-components/lbBasicWordcloud/lb-basic-wordcloud.component';
import { LbValueTableComponent } from '@shared/lbchart-components/lbValueTable/lb-value-table.component';
import { ChartLoadingComponent } from '@shared/components/chart-loading/chart-loading.component';
import { ChartEmptyComponent } from '@shared/components/chart-empty/chart-empty.component'
@Directive({
  selector: '[lbChartId]',
})
export class LbChartWrapperDirective implements OnInit, OnChanges {
  // 图表ID
  @Input('lbChartId') @InputNumber() DAA030: string;

  @Input() querypara = {};

  @Input() height = 200;
  @Input() showheader = true;
  @Input() showfooter = false;
  @Input() headerHeight = 40;
  @Input() footerHeight = 40;

  @Input() outercols;
  @Input() span;

  @Input() outerheadx;
  @Input() outerheadz;

  @Input() sortx = true
  @Input() sortz
  @Input() sortrule = 'ASC'

  // @Input() loading = false;
  // @Output() loadingChange = new EventEmitter();

  chart: any;

  canRun: boolean = true;
  canRuninit = true
  // templateref: TemplateRef<any>

  constructor(
    private chartwrapper: ChartWrapperComponent,
    private message: NzMessageService,
    private lbservice: HttpService,
    private cdr: ChangeDetectorRef,
    private supdata: SupData,
    private resolver: ComponentFactoryResolver,
    private vcr: ViewContainerRef,
  ) {}

  transformdata(data, computedzbobj, selecteditems, dx, dz) {
    // let daa020 = this.daa020
    const self = this;
    let datas = [];
    let z;
    const keymap = {};
    let orgData: any[] = data;

    // let datatemp
    // 计算显示问题
    if (computedzbobj) {
      const dae005 = computedzbobj;
      if (dae005 && Object.keys(dae005).length > 0) {
        Object.keys(dae005).forEach((k: string) => {
          const dae = dae005[k];
          if (dae.J) {
            const bl = dae.J.split('*');
            orgData = this.supdata.rescalc(
              orgData,
              {
                key: k,
              },
              dae.J,
              dx,
              dz,
            );
          }
          // if (dae.D) {
          //   row[k] = row[k] + dae.D
          // }
        });
      }
    }

    // console.log(orgData)

    if (selecteditems.length > 1) {
      for (const key of Object.keys(orgData)) {
        if (selecteditems.indexOf(key) > -1) {
          datas = [
            ...datas,
            ...orgData[key].list.map(m => {
              return {
                item: orgData[key].DAA022,
                ...m,
              };
            }),
          ];
          keymap[key] = orgData[key].DAA022;
        }
      }
      // this.dz = 'dz'
      z = 'item';
    } else if (selecteditems.length === 1) {
      selecteditems.forEach(key => {
        datas = orgData[key].list;

        keymap[key] = orgData[key].DAA022;
      });
    }

    return { datas, z, keymap };
  }
  // <nz-spin nzSimple [nzSize]="'large'"></nz-spin>
  commonStyleHandle(chart, style) {
    // console.log(this.headerHeight)
    // console.log(this.footerHeight)
    chart.height =
      this.height -
      (this.showheader ? this.headerHeight : 0) -
      (this.showfooter ? this.footerHeight : 0) -
      20;
    // console.log(chart.height)

    for (const key of Object.keys(style)) {
      if (typeof style[key] === 'object') {
        for (const key1 of Object.keys(style[key])) {
          chart[key.toString() + key1] = style[key][key1];
        }
      }
    }
  }

  createChart(type) {
    const _vcr = this.chartwrapper.content;
    _vcr.clear();
    const components = {
      basicbar: () => LbBasicBarComponent,
      groupbar: () => LbGroupBarComponent,
      stackbar: () => LbStackBarComponent,
      basicline: () => LbBasicLineComponent,
      mutipleline: () => LbMutipleLineComponent,
      basicpie: () => LbBasicPieComponent,
      nightingalepie: () => LbNightingalePieComponent,
      basicpoint: () => LbBasicPointComponent,
      grouppoint: () => LbGroupPointComponent,
      stackline: () => LbStackLineComponent,
      basicheatmap: () => LbBasicHeatmapComponent,
      basicgauge: () => LbBasicGaugeComponent,
      basicfunnel: () => LbBasicFunnelComponent,
      basicradar: () => LbBasicRadarComponent,
      stackpie: () => LbStackPieComponent,
      basicwordcloud: () => LbBasicWordcloudComponent,
      valuetable: () => LbValueTableComponent,

      loading: () => ChartLoadingComponent,
      empty: () => ChartEmptyComponent,
    };
    return _vcr.createComponent(
      this.resolver.resolveComponentFactory(components[type].apply(this)),
    );
  }

  // queryAndRenderChart() {
  //   this.lbservice
  //     .lbservice('TB_TBXX', {
  //       para: { DAA030: this.DAA030, Q: this.querypara },
  //     })
  //     .then(resdata => {
  //       console.log(resdata);
  //       if (resdata.code < 1) {
  //         this.message.error(resdata.errmsg);
  //       } else {
  //         const dataFilds: string[] = resdata.message.tb.DAA035.split(','); // 指标数组
  //         const groupFileds: string[] = [];
  //         // resdata.message.tb.DAA036 ? resdata.message.tb.DAA036.split(',') : [];
  //         if (resdata.message.tb.DAA043)
  //           groupFileds.push(resdata.message.tb.DAA043); // 维度x
  //         if (resdata.message.tb.DAA044)
  //           groupFileds.push(resdata.message.tb.DAA044); // 维度z
  //         this.chart = this.createChart(resdata.message.tb.DAA033);
  //         console.log('ngInit one time');
  //         let data = this.supdata.rebuildData(
  //           resdata.message.data,
  //           resdata.message.tb,
  //           groupFileds,
  //           groupFileds,
  //         );
  //         data = this.supdata.rebuildDsDataToLabel(data);
  //         if (dataFilds.length > 1) {
  //           data = this.supdata.partition(
  //             data,
  //             this.supdata.getKeyFeild(resdata.message.data),
  //           );
  //           this.chart.instance.position = {
  //             x: groupFileds[0],
  //             y: 'val',
  //             z: 'item',
  //           };
  //         } else {
  //           this.chart.instance.position = {
  //             x: groupFileds[0],
  //             y: dataFilds[0],
  //             z: groupFileds[1],
  //           };
  //         }
  //         this.chart.instance.data = data;
  //         console.log(this.chart.instance.position);
  //         console.log(this.chart.instance.data);
  //         try {
  //           const style = JSON.parse(resdata.message.tb.DAA040);
  //           this.commonStyleHandle(this.chart.instance, style);
  //         } catch (err) {
  //           this.message.error('图表参数配置错误');
  //         }
  //       }
  //     });
  // }

  ngOnInit(): void {
    // this.loading = true;
    // this.loadingChange.emit(this.loading);
    // this.queryAndRenderChart()
      // const self = this;
      // if (!this.canRuninit) {
      //   // 判断是否已空闲，如果在执行中，则直接return
      //   return;
      // }
      // this.canRuninit = false;
      // setTimeout(function() {
      //   self.emitChange(undefined);
      //   self.canRuninit = true;
      // }, 300);
  }

  emitChange(changes: any) {
    // console.log('chjart wrapr pdirective change')
    let param: any;
    if(changes) {
      if (changes.DAA030) {
        // console.log('DAA030 changed')
        param = { DAA030: this.DAA030, Q: this.querypara };
      } else {
        param = {
          DAA030: this.DAA030,
          Q: this.querypara,
          outercols: this.outercols,
        };
      }
      // if (!changes.firstChange && this.outercols === undefined) return;
    }
    
    // this.loading = true;
    // this.loadingChange.emit(this.loading);
    const _vcr = this.chartwrapper.content;
    _vcr.clear();
    const loading = this.createChart('loading');
    // loading.instance.nzSize = 'large'
    // console.log('ng-on-change')
    this.lbservice
      .lbservice('TB_TBXX', {
        para: param,
      })
      .then(resdata => {
        if (resdata.code < 1) {
          this.message.error(resdata.errmsg);
        } else {
          // console.log(resdata)
          let dataFilds: string[] = resdata.message.tb.DAA035.split(','); // 指标数组
          const groupFileds: string[] = [];
          // resdata.message.tb.DAA036 ? resdata.message.tb.DAA036.split(',') : [];

          let computedZbObj, selectedItmes;
          try {
            computedZbObj = JSON.parse(resdata.message.tb.DAE005);
          } catch (err) {
            computedZbObj = undefined;
          }
          try {
            selectedItmes = JSON.parse(resdata.message.tb.DAA045);
          } catch (err) {
            selectedItmes = undefined;
          }
          // const DAE005 = resdata.message.tb.DAE005 // 其中包含计算公式
          // const DAA045 = resdata.message.tb.DAA045 // 勾选的字段， 过滤不想使用的字段

          // console.log(this.outercols)
          if (this.outercols) {
            groupFileds.push(this.outercols); // 维度x
          } else {
            if (resdata.message.tb.DAA043)
              groupFileds.push(resdata.message.tb.DAA043); // 维度x
          }
          if (resdata.message.tb.DAA044)
            groupFileds.push(resdata.message.tb.DAA044); // 维度z

          this.chart = this.createChart(resdata.message.tb.DAA033);

          // console.log('computedZbObj')
          // console.log(computedZbObj)
          // console.log('selectedItmes')
          // console.log(selectedItmes)

          const { datas, z, keymap } = this.transformdata(
            resdata.message.data,
            computedZbObj,
            selectedItmes ? selectedItmes : dataFilds,
            resdata.message.tb.DAA043,
            resdata.message.tb.DAA044,
          );

          // let data = this.supdata.rebuildData(
          //   resdata.message.data,
          //   resdata.message.tb,
          //   groupFileds,
          //   groupFileds,
          // );

          // console.log(resdata.message.tb.DAA033)
          // console.log(JSON.stringify(datas))

          dataFilds = selectedItmes ? selectedItmes : dataFilds;

          
          // console.log(dataFilds)
          // console.log(data)
          if (dataFilds.length > 1) {
            // data = this.supdata.partition(
            //   data,
            //   this.supdata.getKeyFeild(resdata.message.data),
            // );


            //resdata.message.tb.DAA048 === '1'?'item':
            //resdata.message.tb.DAA048 === '1'?groupFileds[0]:
            this.chart.instance.position =
              groupFileds.length > 0
                ? {
                    x: resdata.message.tb.DAA048 === '1'?'item':groupFileds[0],
                    y: 'VAL',
                    z: resdata.message.tb.DAA048 === '1'?groupFileds[0]:'item',
                  }
                : {
                    x: 'item',
                    y: 'VAL',
                  };
            // console.log('1')
          } else {
            // console.log('groupFileds')
            // console.log(groupFileds)
            this.chart.instance.position = {
              x: groupFileds[0],
              y: 'VAL',
              z: groupFileds[1],
            };
            // console.log('2')
          }

          const dv = new DataSet.View().source(datas);
          if(this.sortx && !this.sortz) {
            dv.transform({
              type: 'sort-by',
              fields: [ this.chart.instance.position.x ], // 根据指定的字段集进行排序，与lodash的sortBy行为一致
              order: this.sortrule,        // 默认为 ASC，DESC 则为逆序
            })
          } else if(!this.sortx && this.sortz){
            dv.transform({
              type: 'sort-by',
              fields: [ this.chart.instance.position.z ], // 根据指定的字段集进行排序，与lodash的sortBy行为一致
              order: this.sortrule,   // 默认为 ASC，DESC 则为逆序
            })
          } else if(this.sortx && this.sortz) {
            dv.transform({
              type: 'sort-by',
              fields: [ this.chart.instance.position.x, this.chart.instance.position.z ], // 根据指定的字段集进行排序，与lodash的sortBy行为一致
              order: this.sortrule,   // 默认为 ASC，DESC 则为逆序
            })
          }   

          let data = this.supdata.rebuildDsDataToLabel(dv.rows);
          // console.log(this.chart.instance.position)
          // console.log(data)
          this.chart.instance.data = data;
          // try {
          //   this.chartwrapper.perspective = JSON.parse(resdata.message.tb.DAA042)
          // } catch(err) {
          //   this.chartwrapper.perspective = []
          // }
          // console.log(resdata.message.tb)
          // console.log(data)
          if(Array.isArray(data) && data.length <= 0) {
            const height =   this.height -
            (this.showheader ? this.headerHeight : 0) -
            (this.showfooter ? this.footerHeight : 0) -
            20;
            const empty = this.createChart('empty');
            // empty.instance.margintop = ((height - 130) > 0? (height - 130): 0) / 2
          }
          

          try {
            const style = JSON.parse(resdata.message.tb.DAA040);
            this.commonStyleHandle(this.chart.instance, style);
          } catch (err) {
            this.message.error('图表参数配置错误');
          }
          // console.log(this.chart.instance)

          // this.chart.instance.attachChart();

          // this.loading = false;
          // this.loadingChange.emit(this.loading);
        }
      });
  }

  ngOnChanges(changes: import('@angular/core').SimpleChanges): void {
    if (!changes.firstChange) {
      if (!this.canRun) {
        // 判断是否已空闲，如果在执行中，则直接return
        return;
      }
      this.canRun = false;
      setTimeout(() => {
        this.emitChange(changes);
        this.canRun = true;
      }, 300);
      
    }
    //  const obs = new Observable(subscriber => {
    //   this.emitChange(changes)
    //  })
    //   const clicks = fromEvent(document, 'emitChange');
    //   const result = obs.pipe(throttle(ev => interval(300)));
    //   result.subscribe(x => console.log(x));

    // this.emitChange(changes)
  }
}
